#include "pwm.h"

#define LED_PIN 7

#define LEDC_TIMER              LEDC_TIMER_0
#define LEDC_MODE               LEDC_LOW_SPEED_MODE
#define LEDC_OUTPUT_IO          LED_PIN // Define the output GPIO
#define LEDC_CHANNEL            LEDC_CHANNEL_0
#define LEDC_DUTY_RES           LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
#define LEDC_DUTY               (205)  // Set duty to 2.5%. ((2 ** 13) - 1) * 2.5% = 204.775
#define LEDC_FREQUENCY          (1000)    // Frequency in Hertz. Set frequency at 50 Hz //频率过低会导致闪烁，如30会肉眼可见的闪烁
#define SERVO_MAX_DEGREE        (100)   // Maximum angle in degree upto which servo can rotate

//闪烁
void led_wink(void)
{
	static uint8_t flag =0;
	if(flag == 0)
	{
		gpio_set_level(LED_PIN, 1);//将led引脚配置为高电平;
		flag =1;
	}
	else
	{
		gpio_set_level(LED_PIN, 0);//将led引脚配置为高电平;
		flag =0;
	}
}


static void ledc_pwm_init(void)
{
    // Prepare and then apply the LEDC PWM timer configuration
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_MODE,
        .timer_num        = LEDC_TIMER,
        .duty_resolution  = LEDC_DUTY_RES,
        .freq_hz          = LEDC_FREQUENCY,  // Set output frequency at 5 kHz
        .clk_cfg          = LEDC_AUTO_CLK
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    // Prepare and then apply the LEDC PWM channel configuration
    ledc_channel_config_t ledc_channel = {
        .speed_mode     = LEDC_MODE,
        .channel        = LEDC_CHANNEL,
        .timer_sel      = LEDC_TIMER,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = LEDC_OUTPUT_IO,
        .duty           = 0, // Set duty to 0%
        .hpoint         = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}

static void pwm_breathing_light(void* arg)
{
    // Set the LEDC peripheral configuration
    ledc_pwm_init();
    while (1) {
        for (uint32_t angle = 0; angle < (SERVO_MAX_DEGREE + 1); angle = angle + 1) {
            uint32_t led_duty = (8191 * angle) / 100;   //angle 表示 占空比的变化幅度
            // printf("Angle of rotation: %ld,led_duty: %ld\r\n", (long unsigned int)angle, (long unsigned int)led_duty);
            ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, led_duty);
            ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
            vTaskDelay(pdMS_TO_TICKS(50)); 
        }
        for (uint32_t angle = 100; angle > 0; angle = angle - 1) {
            uint32_t led_duty = (8191 * angle) / 100;   //angle 表示 占空比的变化幅度
            // printf("Angle of rotation: %ld,led_duty: %ld\r\n", (long unsigned int)angle, (long unsigned int)led_duty);
            ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, led_duty);
            ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
            vTaskDelay(pdMS_TO_TICKS(50));
        }
    }
}

void  setLEDBrightness(uint8_t bright_level)
{
    ledc_pwm_init();
    uint32_t led_duty = 8191;

    switch(bright_level)
    {
        case 0: led_duty = 0; break;
        case 1: led_duty /= 12; break;
        case 2: led_duty /= 9; break;
        case 3: led_duty /= 6; break;
        case 4: led_duty /= 3; break;
        case 5: led_duty /= 1; break;
    }

    ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, led_duty);
    ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
}

void breathing_light(void)
{
    xTaskCreate(pwm_breathing_light, "pwm_task_example", 1024, NULL, 10, NULL);
}

void sys_init_led(void)
{
    // Set the LEDC peripheral configuration
    ledc_pwm_init();
    for (uint32_t angle = 0; angle <= 8000; angle += 50)
    {
        ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, angle);
        ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
        vTaskDelay(pdMS_TO_TICKS(10)); 
    }
    for (int angle1 = 8000; angle1 >= 0; angle1 -= 50)  //这里 int 如果用  uint32_t， angle1将会是无符号，一直大于0 ，无法跳出循环
    {
        ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, angle1);
        ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}